import { container } from '../di/container';
import { LoggerToken } from '../domain/interfaces/ILogger';
import type { ILogger } from '../domain/interfaces/ILogger';
import { WebSocketEvents } from '../domain/types';
import { ChatHandlers } from '../application/handlers/chatHandlers';
import { ChatServiceToken } from '../domain/interfaces/IChatService';

export interface CustomWebSocket extends WebSocket {
  id: string;
  user?: any;
  data: {
    userId?: string;
    roomId?: string;
    sessionId?: string;
  };
}

export class WebSocketHandler {
  // 延迟解析 logger 与 handlers，避免模块加载时解析导致容器未配置的错误
  private static _logger?: ILogger;
  private static _chatHandlers?: ChatHandlers;

  private static get logger(): ILogger {
    if (!this._logger) this._logger = container.resolve<ILogger>(LoggerToken);
    return this._logger;
  }

  private static get chatHandlers(): ChatHandlers {
    if (!this._chatHandlers) this._chatHandlers = container.resolve(ChatHandlers);
    return this._chatHandlers;
  }

  private static get eventHandlers(): Map<string, Function> {
    return new Map([
      ['chat:message', this.chatHandlers.handleChatMessage.bind(this.chatHandlers)],
      ['chat:join_room', this.chatHandlers.handleJoinRoom.bind(this.chatHandlers)],
    ]);
  }

  static onOpen(ws: CustomWebSocket): void {
    ws.id = generateId();
    ws.data = {};
    
    this.logger.info('New connection established', { wsId: ws.id });
    
    this.sendMessage(ws, {
      event: WebSocketEvents.CONNECTION,
      data: { connected: true, wsId: ws.id },
      timestamp: Date.now()
    });
  }

  static async onMessage(ws: CustomWebSocket, message: string): Promise<void> {
    try {
      const parsedMessage = JSON.parse(message);
      const handler = this.eventHandlers.get(parsedMessage.event);

      if (handler) {
        await handler(ws, parsedMessage.data, parsedMessage.requestId);
      } else {
        throw new Error(`Unhandled event: ${parsedMessage.event}`);
      }
    } catch (error) {
      this.logger.error('Message processing failed', error as Error, { message });
      
      this.sendMessage(ws, {
        event: WebSocketEvents.ERROR,
        error: 'Invalid message format',
        timestamp: Date.now()
      });
    }
  }

  static onClose(ws: CustomWebSocket): void {
    this.logger.info('Connection closed', { wsId: ws.id, userId: ws.data.userId });
    // 清理逻辑...
  }

  static sendMessage(ws: CustomWebSocket, message: any): void {
    try {
      if ((ws as any).readyState === 1) {
        ws.send(JSON.stringify(message));
      }
    } catch (e) {
      this.logger.error('Failed to send message to client', e as Error);
    }
  }
}

function generateId(): string {
  return `ws_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
}
